package unidadeControle;

import componentes.Registrador;

import excecao.ExcecaoFimPrograma;
import excecao.ExcecaoGeradorEndereco;
import excecao.ExcecaoMemoriaControle;
import excecao.ExcecaoRegistrador;


public class UnidadeControle {
	
	private int pulso;

	// Registrador com endereço da microinstrução que está sendo executada
	private Registrador regEndereco;
	
	// Para ser mais fácil de exibir na tela 
	private String nomeMicroinstrucao;
	
	public UnidadeControle() {
		this.pulso = 0;
		this.nomeMicroinstrucao = "";
		
		GeradorEndereco.criaInstancia();
		
		MemoriaControle.criaInstancia();
		
		this.regEndereco = new Registrador("Rend(UC)");
	}
	
	public String geraSinalControle(String flags, String codInstrucao) throws ExcecaoGeradorEndereco, ExcecaoMemoriaControle, ExcecaoFimPrograma, ExcecaoRegistrador{
		Integer pos = GeradorEndereco.getInstancia().getEnderecoMicroInstrucao(flags, codInstrucao, this.regEndereco.getRegistro());
		
		if (pos == -1){
			throw new ExcecaoFimPrograma();
		}
		
		MicroInstrucao micro = MemoriaControle.getInstancia().getMicroInstrucao(pos);
		
		this.nomeMicroinstrucao = micro.getNome();
		
		switch (this.pulso){
			case 0:
				this.pulso = (this.pulso+1) % 3;
				return micro.getT1();
			case 1:
				this.pulso = (this.pulso+1) % 3;
				return micro.getT2();
			case 2:
				this.pulso = (this.pulso+1) % 3;
				GeradorEndereco.getInstancia().incPosicaoMicro(codInstrucao);
				this.regEndereco.setRegistro(pos.toString());
				return micro.getT3();			
		}		
		
		return null;
	}
	
	public void reseta(String registro) throws ExcecaoRegistrador{
		this.pulso = 0;
		this.nomeMicroinstrucao = "";
		this.setRegEndereco(registro);
		GeradorEndereco.getInstancia().reseta();
	}
	
	public void setRegEndereco(String registro) throws ExcecaoRegistrador{
		this.regEndereco.setRegistro(registro);
	}
	
	public String getNomeMicroinstrucao(){
		return this.nomeMicroinstrucao;
	}
}
